﻿Public Class TransfersControl

    Public Sub Init()
        lvwDownloads.ShowGroups = True
        SetupEvents(True)
        LoadDowloadFilesToGUI()
    End Sub
    Public Sub [Stop]()
        SetupEvents(False)
    End Sub

    Private Sub SetupEvents(ByVal startListening As Boolean)
        If startListening Then
            'AddHandler FileShare.UI.Manager.DownloadQueueLoaded, AddressOf EventHandler_DownloadQueueLoaded
            AddHandler EntityHandlers.DownloadsFiles.UpdatedGUI, AddressOf EventHandler_DownloadQueueFilesChanged
            'AddHandler FileShare.UI.Manager.PartUploaded, AddressOf EventHandler_PartUploaded
        Else
            'RemoveHandler FileShare.UI.Manager.DownloadQueueLoaded, AddressOf EventHandler_DownloadQueueLoaded
            RemoveHandler EntityHandlers.DownloadsFiles.UpdatedGUI, AddressOf EventHandler_DownloadQueueFilesChanged
            'RemoveHandler FileShare.UI.Manager.PartUploaded, AddressOf EventHandler_PartUploaded
        End If
    End Sub

    Private Sub LoadDowloadFilesToGUI()
        For Each clsListView As ListView In New ListView() {lvwDownloads, lvwCompleted, lvwRecycled}
            clsListView.Items.Clear()
            clsListView.Groups.Clear()
        Next
        UpdateFiles(EntityHandlers.DownloadsFiles.GetAll)
    End Sub

    Private Sub EventHandler_DownloadQueueFilesChanged(ByVal file As Entities.Downloads.File)
        Try
            UpdateFile(file)
        Catch ex As Exception
            Framework.Misc.HandleException(Me, ex)
        End Try
    End Sub

    Private Sub UpdateFile(ByVal file As Entities.Downloads.File)
        UpdateFiles_Start()
        UpdateFilesWorker(file)
        UpdateFiles_End()
    End Sub
    Private Sub UpdateFiles_Start()
        lvwDownloads.BeginUpdate()
        lvwCompleted.BeginUpdate()
        lvwRecycled.BeginUpdate()
    End Sub
    Private Sub UpdateFiles_End()
        lvwDownloads.EndUpdate()
        lvwCompleted.EndUpdate()
        lvwRecycled.EndUpdate()
        UpdateButtonCount(lvwCompleted, tsbCompleted)
        UpdateButtonCount(lvwDownloads, tsbDownloads)
        UpdateButtonCount(lvwRecycled, tsbRecycled)
    End Sub
    Private Sub UpdateFiles(ByVal files As Generic.List(Of Entities.Downloads.File))
        UpdateFiles_Start()
        For Each clsFile As Entities.Downloads.File In files
            UpdateFilesWorker(clsFile)
        Next
        UpdateFiles_End()
    End Sub

    Private Sub UpdateFilesWorker(ByVal file As Entities.Downloads.File)
        'find current listview
        Dim clsCurrentListView As ListView
        If lvwDownloads.Items.ContainsKey(file.Id.ToString) Then
            clsCurrentListView = lvwDownloads
        ElseIf lvwCompleted.Items.ContainsKey(file.Id.ToString) Then
            clsCurrentListView = lvwCompleted
        ElseIf lvwRecycled.Items.ContainsKey(file.Id.ToString) Then
            clsCurrentListView = lvwRecycled
        Else
            clsCurrentListView = Nothing
        End If

        'where should it be
        Dim clsNewListView As ListView
        Select Case file.Status
            Case Entities.Downloads.Status.Waiting, Entities.Downloads.Status.Downloading, Entities.Downloads.Status.Paused, Entities.Downloads.Status.PendingComplete
                clsNewListView = lvwDownloads
            Case Entities.Downloads.Status.Complete
                clsNewListView = lvwCompleted
            Case Entities.Downloads.Status.Recycled
                clsNewListView = lvwRecycled
            Case Else
                clsNewListView = Nothing
        End Select

        Dim clsItem As ListViewItem = Nothing
        'doeas the file already exist in a listview
        If clsCurrentListView IsNot Nothing Then
            'yep, get the listviewitem
            clsItem = clsCurrentListView.Items(file.Id.ToString)
            'and if the current listview is not the same as the new, remove item
            If clsCurrentListView IsNot clsNewListView Then
                'first, save group
                Dim clsGroup As ListViewGroup = clsItem.Group
                'remove item
                clsCurrentListView.Items.RemoveByKey(file.Id.ToString)
                'is the group to which the item belonged empty?
                If clsGroup IsNot Nothing AndAlso clsGroup.Items.Count = 0 Then
                    'remove group
                    clsCurrentListView.Groups.Remove(clsGroup)
                End If
            End If
        End If

        'is the item to be kept in any listview (that is, not deleted)
        If clsNewListView IsNot Nothing Then
            'is the new the same? if so, nothing needs to be done
            If clsNewListView IsNot clsCurrentListView Then
                'ok, we need to insert the item. First, make sure we have one
                clsItem = clsNewListView.Items.Add(file.Id.ToString, String.Empty, CStr(Nothing))
                For i As Integer = 1 To 4
                    clsItem.SubItems.Add(String.Empty)
                Next
                'now, does the group it belongs to exist?
                Dim clsGroup As ListViewGroup = clsNewListView.Groups(file.ItemId.ToString)
                If clsGroup Is Nothing Then
                    'we need to create the group
                    Dim clsDownloadItem As Entities.Downloads.Item = EntityHandlers.DownloadsItems.GetById(file.ItemId)
                    clsGroup = clsNewListView.Groups.Add(clsDownloadItem.Id.ToString, clsDownloadItem.Name)
                    clsGroup.Tag = clsDownloadItem
                End If
                clsItem.Group = clsGroup
            End If
        End If

        If clsItem IsNot Nothing Then
            With clsItem
                .Text = file.Name
                Dim strSize As String = Framework.Misc.ToReadableFileSize(file.Size)
                If .SubItems(1).Text <> strSize Then .SubItems(1).Text = strSize
                Select Case file.Status
                    Case Entities.Downloads.Status.Complete
                        If .SubItems(2).Text <> "Complete" Then .SubItems(2).Text = "Complete"
                        If .SubItems(3).Text <> "100%" Then .SubItems(3).Text = "100%"
                    Case Entities.Downloads.Status.Downloading, Entities.Downloads.Status.Waiting, Entities.Downloads.Status.Paused, Entities.Downloads.Status.PendingComplete
                        Dim strStatus As String = file.Status.ToString
                        If file.Status = Entities.Downloads.Status.PendingComplete Then strStatus = "Completed"
                        If .SubItems(2).Text <> strStatus Then .SubItems(2).Text = strStatus

                        Dim dPercent As Double
                        If file.PartsCompleted < file.PartCount Then
                            dPercent = 100 * CDbl(file.PartsCompleted / file.PartCount)
                        Else
                            dPercent = 100
                        End If
                        Dim strPercent As String = String.Format("{0:0.0}%", dPercent)
                        If .SubItems(3).Text <> strPercent Then .SubItems(3).Text = strPercent
                    Case Entities.Downloads.Status.Recycled
                        If .SubItems(2).Text <> "Recycled" Then .SubItems(2).Text = "Recycled"
                        If file.PartsCompleted = file.PartCount Then
                            If .SubItems(3).Text <> "100%" Then .SubItems(3).Text = "100%"
                        Else
                            Dim dPercent As Double = 100 * CDbl(file.PartsCompleted / file.PartCount)
                            Dim strPercent As String = String.Format("{0:0.0}%", dPercent)
                            If .SubItems(3).Text <> strPercent Then .SubItems(3).Text = strPercent
                        End If
                End Select
                .Tag = file
            End With
        End If
    End Sub
    Private Sub UpdateButtonCount(ByVal listView As ListView, ByVal button As ToolStripButton)
        'if first time called, save the original text in the tag for future use
        If button.Tag Is Nothing Then button.Tag = button.Text
        Dim iCount As Integer = listView.Groups.Count
        If iCount = 0 Then
            button.Text = CStr(button.Tag)
        Else
            button.Text = String.Format("{0} ({1})", button.Tag, iCount)
        End If
    End Sub


    Private Sub StopAndDeleteToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RecycleToolStripMenuItem.Click
        Try
            Dim lvwListView As ListView
            If TabControl1.SelectedTab Is tpDownloads Then
                lvwListView = lvwDownloads
            ElseIf TabControl1.SelectedTab Is tpCompleted Then
                lvwListView = lvwCompleted
            Else
                Throw New NotImplementedException
            End If
            If lvwListView.SelectedItems.Count > 0 Then
                Select Case MessageBox.Show(Me, String.Format("Recycle files below?{0}{0}{1}", vbNewLine, GetSelectedNames(lvwListView)), "Recycle", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2)
                    Case DialogResult.Yes
                    Case Else
                        Return
                End Select
                Dim aFiles As New Generic.List(Of Entities.Downloads.File)
                aFiles = GetSelectedFiles(lvwListView)
                Engine.Manager.RecycleDownloads(aFiles)
            End If
        Catch ex As Exception
            Framework.Misc.HandleException(Me.FindForm, ex)
        End Try
    End Sub

    Private Function GetSelectedNames(ByVal listView As ListView) As String
        Dim clsSB As New System.Text.StringBuilder
        For i As Integer = 0 To listView.SelectedItems.Count - 1
            If i <> 0 Then clsSB.AppendLine()
            Dim clsItem As Entities.Downloads.File = CType(listView.SelectedItems(i).Tag, Entities.Downloads.File)
            clsSB.Append("• ")
            clsSB.Append(clsItem.Name)
        Next
        Return clsSB.ToString
    End Function
    Private Function GetSelectedFiles(ByVal listView As ListView) As Generic.List(Of Entities.Downloads.File)
        Dim aRet As New Generic.List(Of Entities.Downloads.File)
        For Each clsItem As ListViewItem In listView.SelectedItems
            aRet.Add(CType(clsItem.Tag, Entities.Downloads.File))
        Next
        Return aRet
    End Function

    Private Sub ContextMenuStrip1_Opening(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles ContextMenuStrip1.Opening
        Try
            If TabControl1.SelectedTab Is tpDownloads Then
                Dim aSelected As Generic.List(Of Entities.Downloads.File) = GetSelectedFiles(lvwDownloads)
                If aSelected.Count = 0 Then
                    RecycleToolStripMenuItem.Enabled = False
                    PauseResumeToolStripMenuItem.Text = "Pause"
                    DeleteToolStripMenuItem.Enabled = False
                    PauseResumeToolStripMenuItem.Enabled = False
                Else
                    Dim blnAllPaused As Boolean = True
                    Dim blnAllPauseable As Boolean = True
                    For Each clsFile As Entities.Downloads.File In aSelected
                        Select Case clsFile.Status
                            Case Entities.Downloads.Status.Paused
                                blnAllPauseable = False
                            Case Else
                                blnAllPaused = False
                        End Select
                    Next
                    If blnAllPaused Then
                        PauseResumeToolStripMenuItem.Enabled = True
                        PauseResumeToolStripMenuItem.Text = "Resume"
                    ElseIf blnAllPauseable Then
                        PauseResumeToolStripMenuItem.Enabled = True
                        PauseResumeToolStripMenuItem.Text = "Pause"
                    Else
                        PauseResumeToolStripMenuItem.Enabled = False
                        PauseResumeToolStripMenuItem.Text = "Pause"
                    End If
                    RecycleToolStripMenuItem.Enabled = True
                    DeleteToolStripMenuItem.Enabled = True
                End If
            ElseIf TabControl1.SelectedTab Is tpCompleted Then
                PauseResumeToolStripMenuItem.Enabled = False
                If lvwCompleted.SelectedItems.Count = 0 Then
                    RecycleToolStripMenuItem.Enabled = False
                    DeleteToolStripMenuItem.Enabled = False
                Else
                    RecycleToolStripMenuItem.Enabled = True
                    DeleteToolStripMenuItem.Enabled = True
                End If
            ElseIf TabControl1.SelectedTab Is tpRecycled Then
                PauseResumeToolStripMenuItem.Enabled = False
                RecycleToolStripMenuItem.Enabled = False
                If lvwRecycled.SelectedItems.Count = 0 Then
                    DeleteToolStripMenuItem.Enabled = False
                Else
                    DeleteToolStripMenuItem.Enabled = True
                End If
            End If
        Catch ex As Exception
            Framework.Misc.HandleException(Me, ex)
        End Try
    End Sub

    Private Sub tmrUpdateTransferRates_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrUpdateTransferRates.Tick
        Try
            Dim dRates As Generic.Dictionary(Of Integer, Integer)
            dRates = Engine.Manager.GetCurrentReadRatesByFileId()

            For Each clsItem As ListViewItem In lvwDownloads.Items
                Dim clsFile As Entities.Downloads.File = CType(clsItem.Tag, Entities.Downloads.File)
                Dim clsSI As ListViewItem.ListViewSubItem = clsItem.SubItems(4)
                If dRates.ContainsKey(clsFile.Id) Then
                    Dim strRate As String = String.Format("{0:0.0} kb/s", dRates(clsFile.Id) / 1024)
                    If clsSI.Text <> strRate Then clsSI.Text = strRate
                Else
                    If clsSI.Text <> String.Empty Then clsSI.Text = String.Empty
                End If
            Next

        Catch ex As Exception
            Framework.Misc.HandleException(Me, ex)
        End Try
    End Sub

    Private Sub ToolStripButton4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tsbDownloads.Click
        TabControl1.SelectTab(tpDownloads)
        SelectToolStripButton(CType(sender, ToolStripButton))
    End Sub

    Private Sub SelectToolStripButton(ByVal tsb As ToolStripButton)
        tsbRecycled.CheckState = CheckState.Unchecked
        tsbCompleted.CheckState = CheckState.Unchecked
        tsbDownloads.CheckState = CheckState.Unchecked
        tsb.CheckState = CheckState.Checked
    End Sub

    Private Sub ToolStripButton3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tsbCompleted.Click
        TabControl1.SelectTab(tpCompleted)
    End Sub

    Private Sub ToolStripButton2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tsbRecycled.Click
        TabControl1.SelectTab(tpRecycled)
    End Sub

    Private Sub TabControl1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TabControl1.SelectedIndexChanged
        Try
            If TabControl1.SelectedTab Is tpDownloads Then
                SelectToolStripButton(tsbDownloads)
            ElseIf TabControl1.SelectedTab Is tpCompleted Then
                SelectToolStripButton(tsbCompleted)
            ElseIf TabControl1.SelectedTab Is tpRecycled Then
                SelectToolStripButton(tsbRecycled)
            End If
        Catch ex As Exception
            Framework.Misc.HandleException(Me, ex)
        End Try
    End Sub

    Private Sub DeleteToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DeleteToolStripMenuItem.Click
        Try
            Dim lvwListView As ListView
            If TabControl1.SelectedTab Is tpDownloads Then
                lvwListView = lvwDownloads
            ElseIf TabControl1.SelectedTab Is tpCompleted Then
                lvwListView = lvwCompleted
            ElseIf TabControl1.SelectedTab Is tpRecycled Then
                lvwListView = lvwRecycled
            Else
                Throw New NotImplementedException
            End If
            If lvwListView.SelectedItems.Count > 0 Then
                Select Case MessageBox.Show(Me, String.Format("Delete files below?{0}{0}{1}", vbNewLine, GetSelectedNames(lvwListView)), "Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2)
                    Case DialogResult.Yes
                    Case Else
                        Return
                End Select
                Dim aFiles As New Generic.List(Of Entities.Downloads.File)
                aFiles = GetSelectedFiles(lvwListView)
                Engine.Manager.DeleteDownloads(aFiles)
            End If
        Catch ex As Exception
            Framework.Misc.HandleException(Me.FindForm, ex)
        End Try
    End Sub

    Private Sub PauseResumeToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PauseResumeToolStripMenuItem.Click
        Try
            Dim aFiles As New Generic.List(Of Entities.Downloads.File)
            aFiles = GetSelectedFiles(lvwDownloads)
            If aFiles(0).Status = Entities.Downloads.Status.Paused Then
                Engine.Manager.ResumeDownloads(aFiles)
            Else
                Engine.Manager.PauseDownloads(aFiles)
            End If
        Catch ex As Exception
            Framework.Misc.HandleException(Me, ex)
        End Try
    End Sub
End Class
